package ishaportalserver.apps.admin;

import static com.googlecode.objectify.ObjectifyService.ofy;
import ishaportalserver.apps.DataStoreNameSpaces;
import ishaportalserver.shared.apps.admin.RoleProp;
import ishaportalserver.shared.apps.admin.UserProp;
import ishaportalserver.shared.rest.DeleteResponse;
import ishaportalserver.shared.rest.PutResponse;
import ishaportalserver.shared.rest.RestStatus;

import java.util.ArrayList;
import java.util.List;

import com.google.appengine.api.NamespaceManager;
import com.googlecode.objectify.ObjectifyService;

class Repository {
	
	static {
		ObjectifyService.factory().register(RoleEntity.class);
		ObjectifyService.factory().register(UserEntity.class);
	}
	
	private static final String APP = DataStoreNameSpaces.ADMIN;

	PutResponse addRole(String name) {
		
		PutResponse resp = new PutResponse();
								
		//name should not be already present
		long id = getRoleId(name);
		if (0 != id) {
			resp.statusCode = RestStatus.Code.RESOURCE_ALREADY_EXISTS;
			resp.message = "Role [" + name + "] is already present with id [" + id + "]";			
			return resp;			
		}
		
		RoleEntity entity = new RoleEntity();
		entity.name = name;
		
		NamespaceManager.set(APP);
		ofy().save().entity(entity).now();
		
		resp.statusCode = RestStatus.Code.SUCCESS;
		resp.resourceId = entity.id;
		
		return resp;
	}

	List<RoleProp> getAllRoles() {
		
		NamespaceManager.set(APP);
		
		List<RoleEntity> entities = ofy().load().type(RoleEntity.class).list();		
		List<RoleProp> props = new ArrayList<RoleProp>();
		
		for (RoleEntity e : entities) {
			props.add(e.toProp());
		}
		
		return props;
	}	
	
	List<UserProp> getAllUsers() {
		
		NamespaceManager.set(APP);
		
		List<UserEntity> entities = ofy().load().type(UserEntity.class).list();		
		List<UserProp> props = new ArrayList<UserProp>();
		
		for (UserEntity e : entities) {
			props.add(e.toProp());
		}
		
		return props;
	}


	PutResponse updateRole(long id, String name) {
		
		NamespaceManager.set(APP);
		
		RoleEntity entity = ofy().load().type(RoleEntity.class).id(id).get();
		
		PutResponse resp = new PutResponse();
		
		//check if id is valid
		if (null == entity) {			
			resp.statusCode = RestStatus.Code.RESOURCE_DOES_NOT_EXIST;
			resp.message = "There is no existing center with id [" + id + "]";
			return resp;
		}
		
		//if new name is different - check if it is valid
		if (! entity.name.toLowerCase().equals(name.toLowerCase())) {
			long roldId = getRoleId(name);
			if (0 != roldId) {				
				resp.statusCode = RestStatus.Code.RESOURCE_ALREADY_EXISTS;
				resp.message = "Role [" + name + "] is already present with id [" + id + "]";			
				return resp;			
			}
		}
		
		//save with new name
		entity.name = name;
		ofy().save().entity(entity).now();
		resp.statusCode = RestStatus.Code.SUCCESS;
		resp.resourceId = entity.id;
		
		return resp;		
	}

	PutResponse addUser(String email) {
		
		PutResponse resp = new PutResponse();				
				
		//email should not be already present
		UserProp prop = getUser(email);
		if (null != prop) {
			resp.statusCode = RestStatus.Code.RESOURCE_ALREADY_EXISTS;
			resp.message = "User [" + email + "] is already present with id [" + prop.id + "]";	
			return resp;			
		}
		
		UserEntity entity = new UserEntity();
		entity.email = email.toLowerCase();
		
		NamespaceManager.set(APP);
		ofy().save().entity(entity).now();
		
		resp.statusCode = RestStatus.Code.SUCCESS;
		resp.resourceId = entity.id;
		
		return resp;
	}

	PutResponse updateUser(long id, String email) {
		
		NamespaceManager.set(APP);
		
		UserEntity entity = ofy().load().type(UserEntity.class).id(id).get();
		
		PutResponse resp = new PutResponse();
		
		//check if id is valid
		if (null == entity) {			
			resp.statusCode = RestStatus.Code.RESOURCE_DOES_NOT_EXIST;
			resp.message = "There is no existing center with id [" + id + "]";
			return resp;
		}
		
		//if new name is different - check if it is valid
		if (! entity.email.toLowerCase().equals(email.toLowerCase())) {
			long roldId = getRoleId(email);
			if (0 != roldId) {				
				resp.statusCode = RestStatus.Code.RESOURCE_ALREADY_EXISTS;
				resp.message = "User [" + email + "] is already present with id [" + id + "]";			
				return resp;			
			}
		}
		
		//save with new name
		entity.email = email;
		ofy().save().entity(entity).now();
		resp.statusCode = RestStatus.Code.SUCCESS;
		resp.resourceId = entity.id;
		
		return resp;		
	}

	UserProp getUser(String email) {
		NamespaceManager.set(APP);
		
		UserEntity entity = ofy().load().type(UserEntity.class).
				filter("email", email.toLowerCase()).first().get();
				
		UserProp prop = null;
		if (null != entity)
			prop = entity.toProp();
		
		return prop;
	}

	DeleteResponse deleteRole(long id) {
		NamespaceManager.set(APP);
		RoleEntity entity = ofy().load().type(RoleEntity.class).id(id).get();
		
		DeleteResponse resp = new DeleteResponse();
		if (null == entity) {
			resp.statusCode = RestStatus.Code.RESOURCE_DOES_NOT_EXIST;
			resp.message = "There is no role with id [" + id + "]";
			return resp;
		}
		
		ofy().delete().entity(entity).now();
		resp.statusCode = RestStatus.Code.SUCCESS;
		
		//TODO - check no existing users before deleting role
		
		return resp;
	}	
	
	private long getRoleId(String name) {
		Repository r = new Repository();					
		List<RoleProp> all = r.getAllRoles();
		
		name = name.toLowerCase();
		long centerId = 0;
		for (RoleProp prop : all) {
			if (prop.name.toLowerCase().equals(name))
				centerId = prop.id;
		}
				
		return centerId;			
	}
	
	RoleProp getRole(long id) {
		NamespaceManager.set(DataStoreNameSpaces.ADMIN);
		
		RoleEntity entity = ofy().load().type(RoleEntity.class).id(id).get();
		
		RoleProp prop = null;
		if (null != entity) 
			prop = entity.toProp();
		
		return prop;
	}

}
